package com.ufgov.smartclient.component.table;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import javax.swing.event.TableColumnModelEvent;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;

/**
 * <p>Title: com.ufgov.smartclient.component</p>
 * <p>Description: 具有隐藏功能的TableColumnModel</p>
 * <p>Copyright: Copyright 2010 ufgov, Inc.</p>
 * <p>Company: ufgov</p>
 * <p>创建时间: 2010-4-1</p>
 * @author 刘永伟(manlge)
 * @version 1.0
 */
public class HideableTableColumnModel extends DefaultTableColumnModel {

  /**
   * 已经隐藏的TableColumn
   */
  private List<TableColumn> hidedTableColumns = new Vector<TableColumn>();

  private TableColumn[] showingColumns = new TableColumn[0];

  @Override
  public void addColumn(TableColumn aColumn) {
    if (aColumn == null) {
      throw new IllegalArgumentException("Object is null");
    }
    //如果在已经隐藏的colum列表中存在，则直接从隐藏列表中删除
    if (hidedTableColumns.remove(aColumn)) {
      totalColumnWidth = -1;
      reset();
      fireColumnAdded(new TableColumnModelEvent(this, 0, getColumnIndex(aColumn
        .getIdentifier())));
    } else {
      if (aColumn == null) {
        throw new IllegalArgumentException("Object is null");
      }
      tableColumns.addElement(aColumn);
      aColumn.addPropertyChangeListener(this);
      totalColumnWidth = -1;
      reset();
      fireColumnAdded(new TableColumnModelEvent(this, 0, getColumnCount() - 1));
    }
  }

  /* 
   * 覆盖原方法，从正在显示的列表中返回TableColumn
   * @see javax.swing.table.DefaultTableColumnModel#getColumn(int)
   */
  @Override
  public TableColumn getColumn(int columnIndex) {
    return getShowingColumns()[columnIndex];
  }

  /* 
   * 返回下在显示的ColumnCount
   * @see javax.swing.table.DefaultTableColumnModel#getColumnCount()
   */
  @Override
  public int getColumnCount() {
    int size = getShowingColumns().length;
    return size;
  }

  @Override
  public int getColumnIndex(Object columnIdentifier) {
    if (columnIdentifier == null)
      throw new IllegalArgumentException("columnIdentifier can't be null");
    TableColumn[] tableColumns = getShowingColumns();
    for (int i = 0; i < tableColumns.length; i++) {
      if (columnIdentifier.equals(tableColumns[i].getIdentifier())) {
        return i;
      }
    }
    throw new IllegalArgumentException("Identifier not found");
  }

  /**
   * @return 正在显示的TableColumn
   * @see #getColumnCount()
   * @see #getColumn(int)
   */
  public TableColumn[] getShowingColumns() {

    return showingColumns;
  }

  /**
   * 重置 {@link #showingColumns} member
   */
  private void reset() {
    Enumeration<TableColumn> columns = super.getColumns();
    ArrayList<TableColumn> list = Collections.list(columns);
    list.removeAll(hidedTableColumns);
    showingColumns = list.toArray(new TableColumn[list.size()]);
  }

  @Override
  public Enumeration<TableColumn> getColumns() {
    return Collections.enumeration(Arrays.asList(getShowingColumns()));
  }

  /**
   * @param aColumn 指定列对应的原始的列的index
   * @return
   */
  private int getOrginalIndex(TableColumn aColumn) {
    for (int i = 0; i < tableColumns.size(); i++) {
      if (aColumn == tableColumns.get(i))
        return i;
    }
    return -1;
  }

  @Override
  public void moveColumn(int columnIndex, int newIndex) {
    if ((columnIndex < 0) || (columnIndex >= getColumnCount()) || (newIndex < 0)
      || (newIndex >= getColumnCount()))
      throw new IllegalArgumentException("moveColumn() - Index out of range");

    TableColumn aColumn;
    if (columnIndex == newIndex) {
      fireColumnMoved(new TableColumnModelEvent(this, columnIndex, newIndex));
      return;
    }

    TableColumn aColumn2 = getShowingColumns()[newIndex];
    aColumn = getShowingColumns()[columnIndex];
    int orginalIndex = getOrginalIndex(aColumn2);

    tableColumns.removeElementAt(getOrginalIndex(aColumn));

    boolean selected = selectionModel.isSelectedIndex(columnIndex);

    selectionModel.removeIndexInterval(columnIndex, columnIndex);

    tableColumns.insertElementAt(aColumn, orginalIndex);
    selectionModel.insertIndexInterval(newIndex, 1, true);
    if (selected) {
      selectionModel.addSelectionInterval(newIndex, newIndex);
    } else {
      selectionModel.removeSelectionInterval(newIndex, newIndex);
    }

    reset();
    fireColumnMoved(new TableColumnModelEvent(this, columnIndex, newIndex));
  }

  /**
   * 返回所有的列，包括隐藏的
   * @return
   * Deprecated 
   */
  public TableColumn[] getAllTableColumns() {
    return tableColumns.toArray(new TableColumn[tableColumns.size()]);
  }

  /**
   * @return 所有的列，包括隐藏的
   * @deprecated {@link #getAllTableColumns()}
   */
  @Deprecated
  public TableColumn[] getAllTableColumn() {
    return getAllTableColumns();
  }

  @Override
  protected void recalcWidthCache() {
    Enumeration enumeration = getColumns();
    totalColumnWidth = 0;
    while (enumeration.hasMoreElements()) {
      TableColumn tableColumn = (TableColumn) enumeration.nextElement();
      totalColumnWidth += tableColumn.getWidth();
    }
  }

  @Override
  public void removeColumn(TableColumn column) {
    int columnIndex = tableColumns.indexOf(column);
    if (columnIndex != -1) {
      hidedTableColumns.add(column);
      if (selectionModel != null) {
        selectionModel.removeIndexInterval(columnIndex, columnIndex);
      }
      totalColumnWidth = -1;
      reset();
      fireColumnRemoved(new TableColumnModelEvent(this, columnIndex, 0));
    }
  }

  /**
   * @return 已经隐藏的TableColumn列表
   */
  public TableColumn[] getHidedTableColumns() {
    return hidedTableColumns.toArray(new TableColumn[hidedTableColumns.size()]);
  }
}
